﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Data;
using System.IO;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using ActiproSoftware.SyntaxEditor;
using ActiproSoftware.SyntaxEditor.Addons.DotNet.Dom;
using ActiproSoftware.SyntaxEditor.Addons.Dynamic;
// using ActiproSoftware.SyntaxEditor.Addons.Xml;
using ActiproSoftware.SyntaxEditor.Commands;
using ActiproSoftware.WinUICore;

namespace WindowsUserControl.Codes
{
    public partial class SourceCodeEditor : UserControl 
    {
        #region events
        #endregion

        #region fields
        /// <summary>
        /// The encryption key to use for encrypted XML files.
        /// </summary>
        private const int EncryptionKey = 5800141;
        private FindReplaceOptions findReplaceOptions = new FindReplaceOptions();
        private FindReplaceForm findReplaceForm;
        private Language _Language;
        private CodeSnippetFolder _CsCodeSnippetFolder;
        private CodeSnippetFolder _VbCodeSnippetFolder;
        private DotNetProjectResolver _ProjectResolver;

        /// <summary>
        /// 
        /// </summary>
        public string Code
        {
            get
            {
                return this.editor.Document.Text;
            }
            set
            {
                this.editor.Document.Text = value;
            }
        }

        #endregion

        /// <summary>
        /// ctor
        /// </summary>
        /// <param name="language"></param>
        public SourceCodeEditor(Language language)
        {
            WindowsApplicationContext winContext = new WindowsApplicationContext();
            InitializeComponent();
            if(Thread.CurrentThread.Name==null)
            {
                Thread.CurrentThread.Name = "User Interface";
            }
            this._Language = language;
            this._ProjectResolver=new DotNetProjectResolver();
            this._CsCodeSnippetFolder =
                new CodeSnippetFolder("C#", winContext.ProjectPath + @"Snippets\C#");
            this._VbCodeSnippetFolder =
                new CodeSnippetFolder("VB", winContext.ProjectPath + @"Snippets\VB");
            // start the parser service (only call this once at the start of your application)
            SemanticParserService.Start();

            // initialize a .NET project solver with all assemblies in the app domain...
            // in a production app, you should initialize with project referenced assemblies instead 
            // via the various AddExternalReference methods
            WindowsApplicationContext.CacheSplashForm splashForm=new WindowsApplicationContext.CacheSplashForm();
            splashForm.Show();
            splashForm.Refresh();
            this._ProjectResolver.CachePath = winContext.ProjectPath + @"Cache\";
            this._ProjectResolver.AddAllAssembliesInAppDomainAsExternalReferences();
            splashForm.Dispose();

            // load language definition
            this.LoadLanguageDefinition(this._Language);
            this.editor.CurrentLineHighlightingVisible = true;
            //this.editor.Renderer.CurrentLineHighlightBackColor = Color.LightGoldenrodYellow;
            //this.editor.Renderer.CurrentLineHighlightBorderColor = Color.Silver;
            //this.editor.Renderer.CurrentLineHighlightExtendsToMargins = true;
            this.propertyGrid.SelectedObject = this.editor;
            this.documentOutlineTreeView.ImageList = SyntaxEditor.ReflectionImageList;
        }

        #region language switch
        /// <summary>
        /// Loads an encrypted XML language definition into the editor.
        /// </summary>
        private void LoadEncryptedXmlLanguageDefinition()
        {
            try
            {
                DateTime start;

                // Allow the user to pick a language definition file
                openFileDialog.Filter = "Encrypted XML Language Definitions (*.*)|*.*";
                if (openFileDialog.ShowDialog() == DialogResult.Cancel) return;

                // Write console message
                Trace.WriteLine("Load from encrypted XML: " + openFileDialog.FileName);
                start = DateTime.Now;

                // Load from encrypted XML
                editor.Document.LoadLanguageFromXml(openFileDialog.FileName, EncryptionKey);

                // Write console message
                Trace.WriteLine("Load complete: " + (DateTime.Now - start));
                if (editor.Document.Language.Properties["Copyright"] != null)
                    Trace.WriteLine(editor.Document.Language.Properties["Copyright"].Value);
            }
            catch (Exception ex)
            {
                Trace.WriteLine("AN EXCEPTION OCCURRED WHILE LOADING A LANGUAGE DEFINITION:");
                Trace.WriteLine(ex.Message);
                if (!(ex is InvalidLanguageDefinitionException))
                    Trace.WriteLine(ex.StackTrace);
                editor.Document.ResetLanguage();
            }
        }

        /// <summary>
		/// Loads a language definition into the editor.
		/// </summary>
		/// <param name="language">A <c>Language</c> specifying the type of language to load.</param>
        private void LoadLanguageDefinition(Language language)
        {
            WindowsApplicationContext winContext = new WindowsApplicationContext();
            try
            {
                switch (language)
                {
                    case Language.CSharpAddon:
                        this.editor.Document.Language =
                            new ActiproSoftware.SyntaxEditor.Addons.CSharp.CSharpSyntaxLanguage();
                        break;
                    case Language.SimpleAddon:
                        this.editor.Document.Language =
                            new SimpleSyntaxLanguage();
                        break;
                    case Language.VBAddon:
                        this.editor.Document.Language = new ActiproSoftware.SyntaxEditor.Addons.VB.VBSyntaxLanguage();
                        this.editor.Document.AutoCaseCorrectEnabled = true;
                        break;
                    //case Language.XMLAddon:
                    //    this.editor.Document.Language = new ActiproSoftware.SyntaxEditor.Addons.Xml.XmlSyntaxLanguage();
                    //    break;
                    case Language.CustomAddon:
                        OpenFileDialog dlg = new OpenFileDialog();
                        dlg.Filter = "Assembly containing language definitions (*.dll)|*.dll|All files(*.*)|*.*";
                        if (dlg.ShowDialog() == DialogResult.Cancel)
                            break;
                        Assembly addonAssembly = Assembly.LoadFile(dlg.FileName);
                        if (addonAssembly != null)
                        {
                            Type[] types = addonAssembly.GetExportedTypes();
                            ArrayList languageTypes = new ArrayList();
                            foreach (Type type in types)
                            {
                                if ((!type.IsAbstract) && (type.IsSubclassOf(typeof (SyntaxLanguage))))
                                {
                                    languageTypes.Add(type);
                                }
                            }
                            if (languageTypes.Count == 1)
                            {
                                this.editor.Document.Language =
                                    (SyntaxLanguage) Activator.CreateInstance((Type) languageTypes[0], new object[] {});
                            }
                            else
                            {
                                foreach (Type type in languageTypes)
                                {
                                    if (
                                        MessageBox.Show(
                                            string.Format("Would you like to load the '{0}' language add-on?",
                                                          type.FullName), "Load Language Add-on",
                                            MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                                    {
                                        this.editor.Document.Language =
                                            (SyntaxLanguage) Activator.CreateInstance(type, new object[] {});
                                        break;
                                    }
                                }
                            }
                        }
                        break;
                    case Language.Assembly:
                    case Language.BatchFile:
                    case Language.CSharp:
                    case Language.CSS:
                    case Language.HTML:
                    case Language.INIFile:
                    case Language.Java:
                    case Language.JScript:
                    case Language.Lua:
                    case Language.MSIL:
                    case Language.Pascal:
                    case Language.Perl:
                    case Language.PHP:
                    case Language.PowerShell:
                    case Language.Python:
                    case Language.SQL:
                    case Language.VBDotNet:
                    case Language.VBScript:
                    case Language.XAML:
                    case Language.CustomDynamic:
                        DateTime start;
                        string filenameBase;
                        if (language == Language.CustomDynamic)
                        {
                            OpenFileDialog dlg1 = new OpenFileDialog();
                            dlg1.Filter = "Xml language definitions (*.xml)|*.xml";
                            if (dlg1.ShowDialog() == DialogResult.Cancel)
                            {
                                break;
                            }
                            filenameBase = dlg1.FileName.Substring(0, dlg1.FileName.Length - 1);
                        }
                        else
                        {
                            filenameBase = winContext.DynamicLexersPath + "ActiproSoftware." +
                                           language.ToString();
                        }
                        Trace.WriteLine("Load from xml: " + filenameBase + ".xml");
                        start = DateTime.Now;

                        // load from xml
                        this.editor.Document.LoadLanguageFromXml(filenameBase + ".xml", 0);
                        Trace.WriteLine("Load complete: " + (DateTime.Now - start));
                        if (this.editor.Document.Language.Properties["Copyright"] != null)
                        {
                            Trace.WriteLine(this.editor.Document.Language.Properties["Copyright"].Value);
                        }
                        break;
                    default:
                        // plain text
                        this.editor.Document.ResetLanguage();
                        break;
                }

                // only enable lexical/semantic parsing and outlining if the language is not plain text
                // note: that the plain text language still does lexical parsing of text into words but 
                // for this example we want to demo fast performance for large files so we are turning 
                // off lexical/semantic parsing and outlining options in the document
                if (language == Language.None)
                    this.editor.Document.Outlining.Mode = OutliningMode.None;
                else
                    this.editor.Document.Outlining.Mode = OutliningMode.Automatic;
                editor.Document.SemanticParsingEnabled = (language != Language.None);
                editor.Document.LexicalParsingEnabled = (language != Language.None);
            }
            catch(Exception ex)
            {
                Trace.WriteLine("An exception occurred while loading a language definition:");
                Trace.WriteLine(ex.Message);
                if(!(ex is InvalidLanguageDefinitionException))
                {
                    Trace.WriteLine(ex.StackTrace);
                }
                this.editor.Document.ResetLanguage();
            }
        }
        #endregion

        #region doc outline
        private void documentOutlineEnabledCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            this.UpdateDocumentOutline();
        }

        /// <summary>
        /// 
        /// </summary>
        public void UpdateDocumentOutline()
        {
            if(this.documentOutlineEnabledCheckBox.Checked)
            {
                if(this.editor.Document.SemanticParseData is ICompilationUnit)
                {
                    // load the document outline
                    ICompilationUnit compilationUnit = (ICompilationUnit) this.editor.Document.SemanticParseData;
                    new DocumentOutlineUpdater(this.editor.Document.Guid, this.documentOutlineTreeView).Process(
                        compilationUnit);
#if DEBUG
                    Trace.WriteLine(compilationUnit.ToStringTree());
#endif
                    return;
                }
            }
        }

        private void documentOutlineTreeView_DoubleClick(object sender, EventArgs e)
        {
            if(this.documentOutlineTreeView.SelectedNode !=null)
            {
                this.documentOutlineTreeView.SelectedNode.Expand();
                IAstNode node = (IAstNode) this.documentOutlineTreeView.SelectedNode.Tag;
                this.editor.Caret.Offset = node.NavigationOffset;
                this.editor.Focus();
            }
        }
        #endregion

        #region tool bar event handlers
        private void toolBar_ButtonClick(object sender, ToolBarButtonClickEventArgs e)
        {
            AppAction action = (AppAction) Enum.Parse(typeof (AppAction), e.Button.Tag.ToString());
            this.ExecuteAppAction(action);
        }

        private void ExecuteAppAction(AppAction action)
        {
            switch(action)
            {
                case AppAction.EditCapitalize:
                    // capitalize words
                    this.editor.SelectedView.ChangeCharacterCasing(CharacterCasing.Normal);
                    break;
                case AppAction.EditClearBookmarks:
                    this.editor.Document.LineIndicators.Clear(BookmarkLineIndicator.DefaultName);
                    break;
                case AppAction.EditCommentSelection:
                    this.editor.SelectedView.CommentLines();
                    break;
                case AppAction.EditCompleteWord:
                    if(this.editor.SelectedView.GetCurrentLanguageForContext().IntelliPromptMemberListSupported)
                    {
                        this.editor.SelectedView.GetCurrentLanguageForContext().IntelliPromptCompleteWord(this.editor);
                    }
                    break;
                case AppAction.EditConvertSpacesToTabs:
                    this.editor.SelectedView.ConvertSpacesToTabs();
                    break;
                case AppAction.EditConvertTabsToSpaces:
                    this.editor.SelectedView.ConvertTabsToSpaces();
                    break;
                case AppAction.EditCopy:
                    this.editor.SelectedView.CopyToClipboard();
                    break;
                case AppAction.EditCopyAndAppend:
                    this.editor.SelectedView.CopyAndAppendToClipboard();
                    break;
                case AppAction.EditCut:
                    this.editor.SelectedView.CutToClipboard();
                    break;
                case AppAction.EditCutAndAppend:
                    this.editor.SelectedView.CutAndAppendToClipboard();
                    break;
                case AppAction.EditDelete:
                    this.editor.SelectedView.Delete();
                    break;
                case AppAction.EditDeleteBlankLines:
                    this.editor.SelectedView.DeleteBlankLines();
                    break;
                case AppAction.EditDeleteHorizontalWhitespace:
                    this.editor.SelectedView.DeleteHorizontalWhitespace();
                    break;
                case AppAction.EditDeleteLine:
                    this.editor.SelectedView.DeleteLine();
                    break;
                case AppAction.EditDuplicateLine:
                    this.editor.SelectedView.DuplicateLine();
                    break;
                case AppAction.EditEnableBookmark:
                    int index = this.editor.SelectedView.CurrentDocumentLine.LineIndicators.IndexOf(
                        BookmarkLineIndicator.DefaultName);
                    if(index !=-1)
                    {
                        ((BookmarkLineIndicator) this.editor.SelectedView.CurrentDocumentLine.LineIndicators[index]).
                            CanNavigateTo =
                            !((BookmarkLineIndicator) this.editor.SelectedView.CurrentDocumentLine.LineIndicators[index])
                                 .CanNavigateTo;
                        this.editor.Invalidate();
                    }
                    break;
                case AppAction.EditIndent:
                    this.editor.SelectedView.Indent();
                    break;
                case AppAction.EditInsertFile:
                    OpenFileDialog dlg=new OpenFileDialog();
                    dlg.Filter = "Text documents (*.txt)|*.txt|All documents(*.*)|*.*";
                    if(dlg.ShowDialog()==DialogResult.Cancel)
                        break;
                    this.editor.SelectedView.InsertFile(dlg.FileName);
                    break;
                case AppAction.EditListMembers:
                    if(this.editor.SelectedView.GetCurrentLanguageForContext().IntelliPromptMemberListSupported)
                    {
                        this.editor.SelectedView.GetCurrentLanguageForContext().ShowIntelliPromptMemberList(this.editor);
                    }
                    break;
                case AppAction.EditMakeLowercase:
                    this.editor.SelectedView.ChangeCharacterCasing(CharacterCasing.Lower);
                    break;
                case AppAction.EditMakeUppercase:
                    this.editor.SelectedView.ChangeCharacterCasing(CharacterCasing.Upper);
                    break;
                case AppAction.EditNextBookmark:
                    this.editor.SelectedView.GotoNextLineIndicator(BookmarkLineIndicator.DefaultName);
                    break;
                case AppAction.EditOutdent:
                    this.editor.SelectedView.Outdent();
                    break;
                case AppAction.EditParameterInfo:
                    if(this.editor.SelectedView.GetCurrentLanguageForContext().IntelliPromptParameterInfoSupported)
                    {
                        this.editor.SelectedView.GetCurrentLanguageForContext().ShowIntelliPromptParameterInfo(
                            this.editor);
                    }
                    break;
                case AppAction.EditPaste:
                    this.editor.SelectedView.PasteFromClipboard();
                    break;
                case AppAction.EditPreviousBookmark:
                    this.editor.SelectedView.GotoPreviousLineIndicator(BookmarkLineIndicator.DefaultName);
                    break;
                case AppAction.EditQuickInfo:
                    if(this.editor.SelectedView.GetCurrentLanguageForContext().IntelliPromptQuickInfoSupported)
                    {
                        this.editor.SelectedView.GetCurrentLanguageForContext().ShowIntelliPromptQuickInfo(this.editor);
                    }
                    break;
                case AppAction.EditRedo:
                    this.editor.Document.UndoRedo.Redo();
                    break;
                case AppAction.EditTabifySelectedLines:
                    this.editor.SelectedView.TabifySelectedLines();
                    break;
                case AppAction.EditToggleBookmark:
                    if(this.editor.SelectedView.CurrentDocumentLine.LineIndicators.Contains(BookmarkLineIndicator.DefaultName))
                    {
                        this.editor.SelectedView.CurrentDocumentLine.LineIndicators.Clear(BookmarkLineIndicator.DefaultName);
                    }
                    else
                    {
                        this.editor.Document.LineIndicators.Add(new BookmarkLineIndicator(),
                                                                this.editor.Caret.DocumentPosition.Line);
                    }
                    break;
                case AppAction.EditToggleCase:
                    // Toggle the character casing
                    editor.SelectedView.ToggleCharacterCasing();
                    break;
                case AppAction.EditTransposeCharacters:
                    // Transpose characters
                    editor.SelectedView.TransposeCharacters();
                    break;
                case AppAction.EditTransposeLines:
                    // Transpose lines
                    editor.SelectedView.TransposeLines();
                    break;
                case AppAction.EditTransposeWords:
                    // Transpose words
                    editor.SelectedView.TransposeWords();
                    break;
                case AppAction.EditTrimTrailingWhitespace:
                    // Trim the trailing whitespace 
                    editor.SelectedView.TrimTrailingWhitespace();
                    break;
                case AppAction.EditUncommentSelection:
                    // Uncomment the currently selected text
                    editor.SelectedView.UncommentLines();
                    break;
                case AppAction.EditUndo:
                    // Perform an undo action
                    editor.Document.UndoRedo.Undo();
                    break;
                case AppAction.EditUntabifySelectedLines:
                    // Untabify selected lines
                    editor.SelectedView.UntabifySelectedLines();
                    break;
                case AppAction.FileNew:
                    // Simulate creating a new file by clearing the text in the current document
                    editor.Text = "";
                    break;
                case AppAction.FileOpen:
                    {
                        // Show the open file dialog
                        openFileDialog.Filter = "All Documents (*.*)|*.*|C# Documents (*.cs)|*.cs|SQL Documents (*.sql)|*.sql|XML Documents (*.xml)|*.xml";
                        if (openFileDialog.ShowDialog() == DialogResult.Cancel) break;
                        saveFileDialog.FileName = openFileDialog.FileName;

                        // Open the file
                        DateTime start = DateTime.Now;
                        editor.Document.LoadFile(openFileDialog.FileName);
                        Trace.WriteLine("Document loaded in " + (DateTime.Now - start));

                        break;
                    }
                case AppAction.FilePageSetup:
                    {
                        // Show the page setup
                        editor.ShowPageSetupForm(this);
                        break;
                    }
                case AppAction.FilePrint:
                    // Implement to use the DocumentTitle property to make the current filename appear at the top of each page
                    // editor.PrintSettings.DocumentTitle = "<filename>";  

                    // Show the print dialog and print
                    editor.Print(true);
                    break;
                case AppAction.FilePrintPreview:
                    // Implement to use the DocumentTitle property to make the current filename appear at the top of each page
                    // editor.PrintSettings.DocumentTitle = "<filename>";  

                    // Show the print preview dialog
                    editor.PrintPreview();
                    break;
                case AppAction.FileSave:
                    // Save a document
                    saveFileDialog.Filter = "All Documents (*.*)|*.*|C# Documents (*.cs)|*.cs|SQL Documents (*.sql)|*.sql|XML Documents (*.xml)|*.xml";
                    if (saveFileDialog.ShowDialog() == DialogResult.Cancel) break;
                    editor.Document.SaveFile(saveFileDialog.FileName, LineTerminator.CarriageReturnNewline);
                    editor.Document.Modified = false;
                    break;
                case AppAction.FileSaveAsHtml:
                    {
                        // Export to HTML and view it
                        string filename = Path.GetDirectoryName(Application.ExecutablePath) + @"\export.html";
                        editor.Document.SaveFileAsHtml(filename, HtmlExportType.Inline, LineTerminator.CarriageReturnNewline);
                        System.Diagnostics.Process.Start(filename);
                        break;
                    }
                case AppAction.FileSaveAsRtf:
                    {
                        // Export to RTF and view it
                        string filename = Path.GetDirectoryName(Application.ExecutablePath) + @"\export.rtf";
                        editor.Document.SaveFileAsRtf(filename, editor.Font, LineTerminator.CarriageReturnNewline);
                        System.Diagnostics.Process.Start(filename);
                        break;
                    }
                case AppAction.OutliningHideSelection:
                    {
                        // Hide the current selection in an outlining node
                        OutliningNode node = editor.SelectedView.CreateOutliningNodeFromSelection(null);
                        if (node != null)
                        {
                            editor.SelectedView.Selection.StartOffset = node.EndOffset;
                            node.Expanded = false;
                        }
                        break;
                    }
                case AppAction.OutliningStartAutomaticOutlining:
                    // Switch to automatic mode
                    editor.Document.Outlining.Mode = OutliningMode.Automatic;
                    break;
                case AppAction.OutliningStopOutlining:
                    // Clear the outlining hierarchy and switch to manual mode
                    editor.Document.Outlining.Clear();
                    editor.Document.Outlining.Mode = OutliningMode.Manual;
                    editor.RefreshOutlining();
                    break;
                case AppAction.OutliningStopHidingCurrent:
                    {
                        // Remove the current outlining node
                        OutliningNode node = editor.Document.Outlining.RootNode.FindNodeRecursive(editor.Caret.Offset);
                        if (node != null)
                        {
                            TextRange refreshTextRange = new TextRange(node.StartOffset, node.EndOffset);
                            editor.Document.Outlining.Remove(node, false);
                            editor.RefreshOutlining(refreshTextRange);
                        }
                        break;
                    }
                case AppAction.OutliningToggleAllOutlining:
                    {
                        // Toggle all outliing
                        bool collapse = true;
                        if (editor.Document.Outlining.RootNode.Count > 0)
                            collapse = editor.Document.Outlining.RootNode[0].Expanded;
                        OutliningNode node = editor.Document.Outlining.RootNode.FindNodeRecursive(editor.Caret.Offset);
                        if (node != null)
                            collapse = node.Expanded;
                        else if (editor.Caret.Offset > 0)
                        {
                            // Since no node was found at the caret's offset, check to see if there is a node ending right before it
                            node = editor.Document.Outlining.RootNode.FindNodeRecursive(editor.Caret.Offset - 1);
                            if (node != null)
                                collapse = node.Expanded;
                        }
                        if (collapse)
                            editor.Document.Outlining.RootNode.CollapseDescendants();
                        else
                            editor.Document.Outlining.RootNode.ExpandDescendants();
                        break;
                    }
                case AppAction.OutliningToggleOutliningExpansion:
                    {
                        // Toggle outlining expansion
                        OutliningNode node = editor.Document.Outlining.RootNode.FindNodeRecursive(editor.Caret.Offset);
                        if (node != null)
                            node.ToggleExpansion();
                        else if (editor.Caret.Offset > 0)
                        {
                            // Since no node was found at the caret's offset, check to see if there is a node ending right before it
                            node = editor.Document.Outlining.RootNode.FindNodeRecursive(editor.Caret.Offset - 1);
                            if (node != null)
                                node.ToggleExpansion();
                        }
                        break;
                    }
                case AppAction.SearchFindReplace:
                    {
                        // Show the find/replace form 
                        if (findReplaceForm == null)
                        {
                            findReplaceForm = new FindReplaceForm(editor, findReplaceOptions);
                            findReplaceForm.StatusChanged += new FindReplaceStatusChangeEventHandler(findReplaceForm_StatusChanged);
                        }
                        findReplaceForm.Owner = this.ParentForm;
                        if (findReplaceForm.Visible)
                            findReplaceForm.Activate();
                        else
                            findReplaceForm.Show();
                        break;
                    }
                case AppAction.ToolsHighlightingStyleEditor:
                    {
                        // Show the style editor
                        StyleEditorForm form = new StyleEditorForm(editor);
                        form.ShowDialog(this);
                        break;
                    }
                case AppAction.ToolsMacrosCancel:
                    editor.SelectedView.RaiseEditCommand(new CancelMacroRecordingCommand());
                    break;
                case AppAction.ToolsMacrosPause:
                    editor.SelectedView.RaiseEditCommand(new PauseResumeMacroRecordingCommand());
                    break;
                case AppAction.ToolsMacrosRecord:
                    editor.SelectedView.RaiseEditCommand(new ToggleMacroRecordingCommand());
                    break;
                case AppAction.ToolsMacrosRun:
                    editor.SelectedView.RaiseEditCommand(new RunMacroCommand());
                    break;
                case AppAction.ToolsTextStatistics:
                    {
                        // Show the text statistics
                        if (editor.SelectedView.Selection.Length > 0)
                            editor.SelectedView.GetTextStatisticsForSelectedText().Show(this, "Selected Text Statistics");
                        else
                            editor.Document.GetTextStatistics().Show(this, "Document Statistics");
                        break;
                    }
                case AppAction.ToolsSpellCheck:
                    new SpellCheckForm(editor).CheckSpelling();
                    break;
                case AppAction.WindowNoSplits:
                case AppAction.WindowSplitFourWay:
                case AppAction.WindowSplitHorizontally:
                case AppAction.WindowSplitVertically:
                    // Ensure that four-way splitting is allowed
                    editor.SplitType = SyntaxEditorSplitType.FourWay;

                    // Ensure splits are visible
                    switch (action)
                    {
                        case AppAction.WindowNoSplits:
                            editor.HasHorizontalSplit = false;
                            editor.HasVerticalSplit = false;
                            break;
                        case AppAction.WindowSplitFourWay:
                            editor.HasHorizontalSplit = true;
                            editor.HasVerticalSplit = true;
                            break;
                        case AppAction.WindowSplitHorizontally:
                            editor.HasHorizontalSplit = true;
                            editor.HasVerticalSplit = false;
                            break;
                        case AppAction.WindowSplitVertically:
                            editor.HasHorizontalSplit = false;
                            editor.HasVerticalSplit = true;
                            break;
                    }
                    break;
            }
        }

        private void findReplaceForm_StatusChanged(object sender, FindReplaceStatusChangeEventArgs e)
        {
            switch (e.ChangeType)
            {
                case FindReplaceStatusChangeType.Find:
                    this.SetStatusMessage("Find: \"" + e.Options.FindText + "\"");
                    break;
                case FindReplaceStatusChangeType.PastDocumentEnd:
                    this.SetStatusMessage("Past the end of the document");
                    break;
                case FindReplaceStatusChangeType.Ready:
                    this.SetStatusMessage("Ready");
                    break;
                case FindReplaceStatusChangeType.Replace:
                    this.SetStatusMessage("Replace: \"" + e.Options.FindText + "\", with: \"" + e.Options.ReplaceText + "\"");
                    break;
            }
        }
        #endregion

        #region error list/output console
        /// <summary>
        /// Updates the semantic-related user interface controls.
        /// </summary>
        public void UpdateSemanticUI()
        {
            this.UpdateDocumentOutline();
            this.UpdateErrorsList();
        }

        /// <summary>
        /// Updates the errors list.
        /// </summary>
        public void UpdateErrorsList()
        {
            IList syntaxErrors = null;

            // Get the syntax errors collection
            if (editor.Document.SemanticParseData is ICompilationUnit)
                syntaxErrors = ((ICompilationUnit)editor.Document.SemanticParseData).SyntaxErrors;

            if (syntaxErrors != null)
            {
                // Build the errors list (up to 100 errors max)
                errorsListView.BeginUpdate();
                errorsListView.Items.Clear();
                for (int index = 0; (index < 100) && (index < syntaxErrors.Count); index++)
                {
                    SyntaxError error = (SyntaxError)syntaxErrors[index];

                    // Add the error to the listview
                    DocumentPosition documentPosition = editor.Document.OffsetToPosition(error.TextRange.StartOffset);
                    ListViewItem listViewItem = new ListViewItem(new string[] { (documentPosition.Line + 1).ToString(), 
						(documentPosition.Character + 1).ToString(), error.Message });
                    listViewItem.Tag = error.TextRange;
                    errorsListView.Items.Add(listViewItem);
                }
                errorsListView.EndUpdate();
            }
            else
            {
                // Clear the errors 
                errorsListView.Items.Clear();
            }
        }

        /// <summary>
        /// Writes a line to the console textbox.
        /// </summary>
        /// <param name="text">The text to write.</param>
        public void WriteLine(string text)
        {
            // Append the text
            consoleTextBox.Text += (text + "\r\n");

            // Scroll
            consoleTextBox.SelectionStart = consoleTextBox.Text.Length - 2;
            consoleTextBox.ScrollToCaret();
        }
        #endregion

        #region editor event handler
        private void editor_DocumentIndicatorRemoved(object sender, ActiproSoftware.SyntaxEditor.IndicatorEventArgs e)
        {
            // Add status message
            // this.WriteLine("IndicatorRemoved: " + e.ToString());
        }

        private void editor_CodeSnippetFieldActivated(object sender, ActiproSoftware.SyntaxEditor.CodeSnippetFieldEventArgs e)
        {
            this.WriteLine("CodeSnippetFieldActivated: " + e.ToString());
        }

        private void editor_DocumentSyntaxLanguageLoaded(object sender, ActiproSoftware.SyntaxEditor.SyntaxLanguageEventArgs e)
        {
            if (e.Language is ActiproSoftware.SyntaxEditor.Addons.DotNet.Dom.DotNetSyntaxLanguage)
            {
                // Update the language data
                this._ProjectResolver.CodeSnippetFolders.Clear();
                if (e.Language.Key == "C#")
                    this._ProjectResolver.CodeSnippetFolders.Add(this._CsCodeSnippetFolder);
                else
                    this._ProjectResolver.CodeSnippetFolders.Add(this._VbCodeSnippetFolder);
                editor.Document.LanguageData = this._ProjectResolver;
            }
            //else if (e.Language is ActiproSoftware.SyntaxEditor.Addons.Xml.XmlSyntaxLanguage)
            //{
            //    // Update the language data
            //    editor.Document.LanguageData = new ActiproSoftware.SyntaxEditor.Addons.Xml.XmlSchemaResolver();
            //}
            else
            {
                // Clear the language data
                editor.Document.LanguageData = null;
            }

            // Update other UI
            editCommentSelectionButton.Enabled = (e.Language.LineCommentDelimiter != null);
            //editCommentSelectionMenuItem.Enabled = (e.Language.LineCommentDelimiter != null);
            editUncommentSelectionButton.Enabled = (e.Language.LineCommentDelimiter != null);
            //editUncommentSelectionMenuItem.Enabled = (e.Language.LineCommentDelimiter != null);

            // Alter the user interface of the window based on the language
            if (e.Language is ActiproSoftware.SyntaxEditor.Addons.DotNet.Dom.DotNetSyntaxLanguage)
            {
                //typeMemberDropDownList.SyntaxEditor = editor;
                //typeMemberDropDownList.Visible = true;
                rightTabControl.SelectedTab = documentOutlineTabPage;
            }
            //else if ((e.Language is SimpleSyntaxLanguage) || (e.Language is XmlSyntaxLanguage))
            //{
            //    //typeMemberDropDownList.SyntaxEditor = null;
            //    //typeMemberDropDownList.Visible = false;
            //    rightTabControl.SelectedTab = documentOutlineTabPage;
            //}
            else
            {
                //typeMemberDropDownList.SyntaxEditor = null;
                //typeMemberDropDownList.Visible = false;
                rightTabControl.SelectedTab = propertiesTabPage;
            }

            // Get all the languages
            SyntaxLanguageCollection languages = SyntaxLanguage.GetLanguageCollection(e.Language);

            // Add status message
            this.WriteLine("SyntaxLanguageLoaded: " + languages.ToString());
        }

        private void editor_UserInterfaceUpdate(object sender, EventArgs e)
        {
            this.UpdateSemanticUI();
        }

        private void editor_CodeSnippetActivating(object sender, ActiproSoftware.SyntaxEditor.CodeSnippetEventArgs e)
        {
            this.WriteLine("CodeSnippetActivating: "+e.ToString());
        }

        private void editor_DocumentIndicatorAdded(object sender, ActiproSoftware.SyntaxEditor.IndicatorEventArgs e)
        {
            // Add status message
            // this.WriteLine("IndicatorAdded: " + e.ToString());
        }

        private void editor_IntelliPromptMemberListClosing(object sender, CancelEventArgs e)
        {
            // If e.Cancel is false, the user wants to perform an auto-complete... set it to true to cancel automatic auto-complete

            // Add status message
            if (e.Cancel)
                this.WriteLine("IntelliPromptMemberListClosing: (Cancelled)");
            else
                this.WriteLine("IntelliPromptMemberListClosing: Perform auto-complete for " + editor.IntelliPrompt.MemberList.SelectedItem.Text);
        }

        private void editor_KeyTyping(object sender, ActiproSoftware.SyntaxEditor.KeyTypingEventArgs e)
        {
            // Add status message
            // this.WriteLine("KeyTyping: " + e.ToString());

            if (e.KeyChar == '(')
            {
                // Get the offset
                int offset = editor.SelectedView.Selection.EndOffset;

                // Get the text stream
                TextStream stream = editor.Document.GetTextStream(offset);

                // Get the language
                SyntaxLanguage language = stream.Token.Language;

                // If in C#...
                if ((language is DynamicSyntaxLanguage) && (language.Key == "C#"))
                {
                    if ((offset >= 10) && (editor.Document.GetSubstring(offset - 10, 10) == "Invalidate"))
                    {
                        // Show parameter info
                        editor.IntelliPrompt.ParameterInfo.Info.Clear();
                        editor.IntelliPrompt.ParameterInfo.Info.Add(@"void <b>Control.Invalidate</b>()<br/>" +
                            @"Invalidates the entire surface of the control and causes the control to be redrawn.");
                        editor.IntelliPrompt.ParameterInfo.Info.Add(@"void Control.Invalidate(<b>System.Drawing.Rectangle rc</b>, bool invalidateChildren)<br/>" +
                            @"<b>rc:</b> A System.Drawing.Rectangle object that represents the region to invalidate.");
                        editor.IntelliPrompt.ParameterInfo.Show(offset - 10);
                    }
                }
            }
        }

        private void editor_ViewMouseHover(object sender, ActiproSoftware.SyntaxEditor.EditorViewMouseEventArgs e)
        {
            // Add status message
            /*
            if (e.HitTestResult.Token != null)
                this.WriteLine(String.Format("ViewMouseHover: Token={0}", e.HitTestResult.Token.Key));
            else
                this.WriteLine("ViewMouseHover: " + e.ToString());
            */

            if (e.HitTestResult.Token != null)
            {
                // Get the language
                SyntaxLanguage language = e.HitTestResult.Token.Language;

                // If in C#...
                if ((language is DynamicSyntaxLanguage) && (language.Key == "C#"))
                {
                    switch (e.HitTestResult.Token.Key)
                    {
                        case "CommentURLToken":
                        case "MultiLineCommentURLToken":
                        case "XMLCommentURLToken":
                            // This shows how to provide a popup for when the mouse is over a URL in a comment
                            e.ToolTipText = editor.Document.GetTokenText(e.HitTestResult.Token) + "<br/><b>CTRL + click to follow link</b>";
                            break;
                        case "IdentifierToken":
                            // This simple example shows how to display quick info when hovering over an identifier "System"
                            if (editor.Document.GetTokenText(e.HitTestResult.Token) == "System")
                                e.ToolTipText = "namespace <b>System</b>";
                            break;
                    }
                }
            }
        }

        private void editor_CodeSnippetFieldModified(object sender, ActiproSoftware.SyntaxEditor.CodeSnippetFieldEventArgs e)
        {
            this.WriteLine("CodeSnippetFieldModified: " + e.ToString());
        }

        private void editor_SelectedViewChanged(object sender, EventArgs e)
        {
            this.WriteLine("SelectedViewChanged");
        }

        private void editor_IncrementalSearch(object sender, ActiproSoftware.SyntaxEditor.IncrementalSearchEventArgs e)
        {
            switch (e.EventType)
            {
                case IncrementalSearchEventType.Activated:
                case IncrementalSearchEventType.Search:
                    if ((editor.SelectedView.FindReplace.IncrementalSearch.FindText.Length == 0) || (e.ResultSet.Count > 0))
                    {
                        string text = "Incremental Search: " + editor.SelectedView.FindReplace.IncrementalSearch.FindText;
                        if (editor.SelectedView.FindReplace.IncrementalSearch.SearchUp)
                            text = "Reverse " + text;
                        this.SetStatusMessage(text);
                    }
                    else
                    {
                        string text = "Incremental Search: " + editor.SelectedView.FindReplace.IncrementalSearch.FindText + " (not found)";
                        if (editor.SelectedView.FindReplace.IncrementalSearch.SearchUp)
                            text = "Reverse " + text;
                        this.SetStatusMessage(text);
                    }
                    break;
                case IncrementalSearchEventType.Deactivated:
                    this.SetStatusMessage("Ready");
                    break;
                case IncrementalSearchEventType.CharacterIgnored:
                    // This happens if a character is ignored because the current find text was not found in the last search
                    break;
            }
        }

        private void editor_ViewSplitAdded(object sender, ActiproSoftware.SyntaxEditor.SyntaxEditorSplitEventArgs e)
        {
            this.WriteLine("ViewSplitAdded: " + e.ToString());
        }

        private void editor_DocumentTextChanged(object sender, ActiproSoftware.SyntaxEditor.DocumentModificationEventArgs e)
        {
            // Add status message
            // this.WriteLine("TextChanged: " + e.ToString());
        }

        private void editor_SelectionChanged(object sender, ActiproSoftware.SyntaxEditor.SelectionEventArgs e)
        {
            // Add status message
            // this.WriteLine("SelectionChanged: View=" + editor.Views.IndexOf(e.Selection.View) + ", Selection=" + e.Selection);

            // Update the position in the status bar (uses 1-based line character specifications... better for end users)
            positionPanel.Text = "Ln " + e.DisplayCaretDocumentPosition.Line +
                "\tCol " + e.DisplayCaretCharacterColumn +
                "\tCh " + e.DisplayCaretDocumentPosition.Character;

            // Use this for debugging
            // positionPanel.Text = "Off " + editor.Caret.Offset +
            //    	"\tLn " + e.DisplayCaretDocumentPosition.Line + 
            //     	"\tCh " + e.DisplayCaretDocumentPosition.Character;

            // Get information about the current token
            IToken token = editor.Document.Tokens.GetTokenAtOffset(editor.Caret.Offset);

            // Update the panels
            languagePanel.Text = (token.Language != null ? token.Language.Key : editor.Document.Language.Key);
            statePanel.Text = (token.LexicalState != null ? token.LexicalState.Key : "State ID: " + token.LexicalStateID);
            tokenPanel.Text = token.Key + (editor.Caret.Offset == token.StartOffset ? " (*)" : String.Empty);

            if (token.HasFlag(LexicalParseFlags.LanguageStart))
                hierarchyLevelPanel.Text = token.NestingDepth + ">";
            else if (token.HasFlag(LexicalParseFlags.LanguageEnd))
                hierarchyLevelPanel.Text = "<" + token.NestingDepth;
            else if (token.IsDocumentEnd)
                hierarchyLevelPanel.Text = "!" + token.NestingDepth;
            else
                hierarchyLevelPanel.Text = token.NestingDepth.ToString();
        }

        private void editor_TokenMouseLeave(object sender, ActiproSoftware.SyntaxEditor.EditorViewMouseEventArgs e)
        {
            // Add status message
            // this.WriteLine("TokenMouseLeave: " + e.OldMouseOverToken.Key);
        }

        private void editor_ContextMenuRequested(object sender, ActiproSoftware.SyntaxEditor.ContextMenuRequestEventArgs e)
        {
            // You can display your own custom context menu by handling this event.
            // Use the MenuLocation parameter as the location at which to display the custom menu
            // and ensure that SyntaxEditor.DefaultContextMenuEnabled is set to false.
            this.WriteLine("ContextMenuRequested: " + e.MenuLocation);
        }

        private void editor_KeyTyped(object sender, ActiproSoftware.SyntaxEditor.KeyTypedEventArgs e)
        {
            // Add status message
            // this.WriteLine("KeyTyped: " + e.ToString());
        }

        private void editor_SmartIndent(object sender, ActiproSoftware.SyntaxEditor.SmartIndentEventArgs e)
        {
            // By default, SyntaxEditor initializes the e.IndentAmount properly for Block formatting.
            // You can change e.IndentAmount to provide "smart" indenting based on language context.

            if (editor.Document.Language is DynamicSyntaxLanguage)
            {
                // Increment indent if pressing ENTER after a curly brace
                switch (editor.Document.Language.Key)
                {
                    case "C#":
                    case "Java":
                    case "JScript":
                    case "PHP":
                        {
                            TextStream stream = editor.Document.GetTextStream(editor.SelectedView.Selection.FirstOffset);
                            bool exitLoop = false;
                            while (stream.Offset > 0)
                            {
                                stream.GoToPreviousToken();
                                switch (stream.Token.Key)
                                {
                                    case "WhitespaceToken":
                                        // Ignore whitespace
                                        break;
                                    case "OpenCurlyBraceToken":
                                        e.IndentAmount++;
                                        exitLoop = true;
                                        break;
                                    default:
                                        exitLoop = true;
                                        break;
                                }
                                if (exitLoop)
                                    break;
                            }
                            break;
                        }
                }
            }

            // Add status message
            // this.WriteLine("SmartIndent: " + e.IndentAmount + " character(s)");		
        }

        private void editor_CodeSnippetFieldDeactivating(object sender, ActiproSoftware.SyntaxEditor.CodeSnippetFieldEventArgs e)
        {
            this.WriteLine("CodeSnippetFieldDeactivating: " + e.ToString());
        }

        private void editor_CutCopyDrag(object sender, ActiproSoftware.SyntaxEditor.CutCopyDragEventArgs e)
        {
            // Handle this event to store IDataObjects that are sent to the clipboard or provide custom IDataObjects.
            // When a specific IDataObject should be repasted into the document from a custom clipboard ring, 
            // you may call EditorView.PasteFromClipboard(IDataObject).

            // Add status message
            this.WriteLine("CutCopyDrag");
        }

        private void editor_DocumentUndoRedoStateChanged(object sender, ActiproSoftware.SyntaxEditor.UndoRedoStateChangedEventArgs e)
        {
            if (e.EnabledStatesChanged)
            {
                //editUndoMenuItem.Enabled = editor.Document.UndoRedo.CanUndo;
                editUndoButton.Enabled = editor.Document.UndoRedo.CanUndo;
                //editRedoMenuItem.Enabled = editor.Document.UndoRedo.CanRedo;
                editRedoButton.Enabled = editor.Document.UndoRedo.CanRedo;
            }
        }

        private void editor_IntelliPromptMemberListSelectedItemChanged(object sender, EventArgs e)
        {
            // Add status message
            if (editor.IntelliPrompt.MemberList.SelectedItem != null)
                this.WriteLine("IntelliPromptMemberListSelectedItemChanged: " + editor.IntelliPrompt.MemberList.SelectedItem.Text);
            else
                this.WriteLine("IntelliPromptMemberListSelectedItemChanged: (None)");
        }

        private void editor_PasteDragDrop(object sender, ActiproSoftware.SyntaxEditor.PasteDragDropEventArgs e)
        {
            // Add status message if there is no default text
            if (e.Text == null)
                this.WriteLine("PasteDragDrop: " + e.Source);

            // Allow file name drops from Windows Explorer
            if (e.DataObject.GetDataPresent(DataFormats.FileDrop))
            {
                object files = e.DataObject.GetData(DataFormats.FileDrop);
                if ((files is string[]) && (((string[])files).Length > 0))
                {
                    string filename = ((string[])files)[0];

                    // If performing a drop of a .snippet file, see if it contains any code snippets and if so, 
                    //    activate the first one that is found
                    if ((e.Source == PasteDragDropSource.DragDrop) && (Path.GetExtension(filename).ToLower() == ".snippet"))
                    {
                        CodeSnippet[] codeSnippets = CodeSnippet.LoadFromXml(filename);
                        if (codeSnippets.Length > 0)
                        {
                            e.Text = String.Empty;
                            editor.IntelliPrompt.CodeSnippets.Activate(codeSnippets[0]);
                            return;
                        }
                    }

                    // Simply insert the path of the file
                    e.Text = filename;
                }
            }

            // If a paste occurred, show a smart tag for more options
            if ((e.Source == PasteDragDropSource.PasteComplete) && (editor.Caret.Offset > 0))
            {
                editor.IntelliPrompt.SmartTag.Add(new SmartTag("Paste", imageList.Images[editPasteButton.ImageIndex], "Options for <b>post-paste</b> operations."),
                    new TextRange(Math.Max(0, editor.Caret.Offset - e.Text.Length), editor.Caret.Offset));
            }
        }

        private void editor_OverwriteModeChanged(object sender, EventArgs e)
        {
            this.WriteLine("OverwriteModeChanged: " + (editor.OverwriteMode ? "Overwrite" : "Insert") + " mode");
        }

        private void editor_MacroRecordingStateChanged(object sender, EventArgs e)
        {
            this.WriteLine(String.Format("MacroRecordingStateChanged: {0}", editor.MacroRecording.State));

            switch (editor.MacroRecording.State)
            {
                case MacroRecordingState.Recording:
                    //messagePanel.Text = "Macro recording is active";
                    toolsMacrosRunButton.Enabled = false;
                    toolsMacrosRecordButton.ImageIndex = 24;  // Stop button
                    //toolsMacrosRecordMenuItem.ImageIndex = 24;
                    toolsMacrosRecordButton.ToolTipText = "Stop Recording";
                    toolsMacrosPauseButton.Enabled = true;
                    toolsMacrosPauseButton.Pushed = false;
                    toolsMacrosPauseButton.ToolTipText = "Pause Recording";
                    toolsMacrosCancelButton.Enabled = true;
                    break;
                case MacroRecordingState.Paused:
                    //messagePanel.Text = "Macro recording is paused";
                    toolsMacrosPauseButton.Pushed = true;
                    toolsMacrosPauseButton.ToolTipText = "Resume Recording";
                    break;
                default:
                    //messagePanel.Text = null;
                    toolsMacrosRunButton.Enabled = (editor.MacroRecording.LastMacroCommand != null);
                    toolsMacrosRecordButton.ImageIndex = 23;  // Record button
                    //toolsMacrosRecordMenuItem.ImageIndex = 23;
                    toolsMacrosRecordButton.ToolTipText = "Record Macro";
                    toolsMacrosPauseButton.Enabled = false;
                    toolsMacrosPauseButton.Pushed = false;
                    toolsMacrosPauseButton.ToolTipText = "Pause Recording";
                    toolsMacrosCancelButton.Enabled = false;
                    break;
            }

            //toolsMacrosRunMenuItem.Enabled = toolsMacrosRunButton.Enabled;
            //toolsMacrosRecordMenuItem.Text = toolsMacrosRecordButton.ToolTipText;
            //toolsMacrosPauseMenuItem.Enabled = toolsMacrosPauseButton.Enabled;
            //toolsMacrosPauseMenuItem.Text = toolsMacrosPauseButton.ToolTipText;
            //toolsMacrosCancelMenuItem.Enabled = toolsMacrosCancelButton.Enabled;
        }

        private void editor_IntelliPromptSmartTagClicked(object sender, EventArgs e)
        {
            // Add status message
            this.WriteLine("IntelliPromptSmartTagClicked: " + editor.IntelliPrompt.SmartTag.ActiveSmartTag.Key);

            switch (editor.IntelliPrompt.SmartTag.ActiveSmartTag.Key)
            {
                case "Paste":
                    {
                        // Show a post-paste context menu in response to the smart tag being clicked
                        OwnerDrawContextMenu contextMenu = new OwnerDrawContextMenu();
                        contextMenu.ImageList = imageList;
                        contextMenu.MenuItems.Add(new OwnerDrawMenuItem("Undo the Paste Operation", editUndoButton.ImageIndex,
                            new EventHandler(smartTagContextMenuItem_Click), Shortcut.CtrlZ, editor.IntelliPrompt.SmartTag.ActiveSmartTag));
                        contextMenu.MenuItems.Add(new OwnerDrawMenuItem("-"));
                        contextMenu.MenuItems.Add(new OwnerDrawMenuItem("Cancel"));
                        contextMenu.Show(editor, editor.PointToClient(new Point(editor.IntelliPrompt.SmartTag.Bounds.Left, editor.IntelliPrompt.SmartTag.Bounds.Bottom)));
                        break;
                    }
            }

            // Hide the smart tag
            editor.IntelliPrompt.SmartTag.Hide();
        }

        private void smartTagContextMenuItem_Click(object sender, EventArgs e)
        {
            OwnerDrawMenuItem menuItem = (OwnerDrawMenuItem)sender;
            if (menuItem.Text.StartsWith("Undo"))
                editor.Document.UndoRedo.Undo();
        }

        private void editor_DocumentModifiedChanged(object sender, EventArgs e)
        {
            // Add status message
            this.WriteLine("DocumentModifiedChanged: Modified=" + editor.Document.Modified);
        }

        private void editor_AutoReplacePerformed(object sender, ActiproSoftware.SyntaxEditor.AutoReplaceEventArgs e)
        {
            this.WriteLine("AutoReplacePerformed: "+e.ToString());
        }

        private void editor_TriggerActivated(object sender, ActiproSoftware.SyntaxEditor.TriggerEventArgs e)
        {
            // Add status message
            this.WriteLine("TriggerActivated: " + e.ToString());

            switch (editor.Document.Language.Key)
            {
                case "C#":
                    {
                        switch (e.Trigger.Key)
                        {
                            case "MemberListTrigger":
                                {
                                    // Construct full name of item to see if reflection can be used... iterate backwards through the token stream
                                    TokenStream stream = editor.Document.GetTokenStream(editor.Document.Tokens.IndexOf(
                                        editor.SelectedView.Selection.EndOffset - 1));
                                    string fullName = String.Empty;
                                    int periods = 0;
                                    while (stream.Position > 0)
                                    {
                                        IToken token = stream.ReadReverse();
                                        switch (token.Key)
                                        {
                                            case "IdentifierToken":
                                            case "NativeTypeToken":
                                                fullName = editor.Document.GetTokenText(token) + fullName;
                                                break;
                                            case "PunctuationToken":
                                                if ((token.Length == 1) && (editor.Document.GetTokenText(token) == "."))
                                                {
                                                    fullName = editor.Document.GetTokenText(token) + fullName;
                                                    periods++;
                                                }
                                                else
                                                    stream.Position = 0;
                                                break;
                                            default:
                                                stream.Position = 0;
                                                break;
                                        }
                                    }

                                    // Convert common types
                                    if ((fullName.Length > 0) && (periods == 0))
                                    {
                                        switch (fullName)
                                        {
                                            case "bool":
                                                fullName = "System.Boolean";
                                                break;
                                            case "byte":
                                                fullName = "System.Byte";
                                                break;
                                            case "char":
                                                fullName = "System.Char";
                                                break;
                                            case "decimal":
                                                fullName = "System.Decimal";
                                                break;
                                            case "double":
                                                fullName = "System.Double";
                                                break;
                                            case "short":
                                                fullName = "System.Int16";
                                                break;
                                            case "int":
                                                fullName = "System.Int32";
                                                break;
                                            case "long":
                                                fullName = "System.Int64";
                                                break;
                                            case "object":
                                                fullName = "System.Object";
                                                break;
                                            case "sbyte":
                                                fullName = "System.SByte";
                                                break;
                                            case "float":
                                                fullName = "System.Single";
                                                break;
                                            case "string":
                                                fullName = "System.String";
                                                break;
                                            case "ushort":
                                                fullName = "System.UInt16";
                                                break;
                                            case "uint":
                                                fullName = "System.UInt32";
                                                break;
                                            case "ulong":
                                                fullName = "System.UInt64";
                                                break;
                                            case "void":
                                                fullName = "System.Void";
                                                break;
                                        }
                                    }

                                    // If a full name is found...
                                    if (fullName.Length > 0)
                                    {
                                        // Get the member list
                                        IntelliPromptMemberList memberList = editor.IntelliPrompt.MemberList;
                                        memberList.ResetAllowedCharacters();

                                        // Set IntelliPrompt ImageList
                                        memberList.ImageList = documentOutlineTreeView.ImageList;

                                        // Add items to the list
                                        memberList.Clear();

                                        // Find a type that matches the full name
                                        Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
                                        foreach (Assembly assemblyData in assemblies)
                                        {
                                            Type type = assemblyData.GetType(fullName, false, false);
                                            if (type != null)
                                            {
                                                memberList.AddReflectionForTypeMembers(type, IntelliPromptTypeMemberFlags.AllMemberTypes |
                                                    IntelliPromptTypeMemberFlags.AllAccessTypes | IntelliPromptTypeMemberFlags.Static);
                                                break;
                                            }
                                        }

                                        // If no specific type was found... 
                                        if (memberList.Count == 0)
                                        {
                                            // Add namespace to examine
                                            System.Collections.Specialized.StringCollection namespaceNames = new System.Collections.Specialized.StringCollection();
                                            namespaceNames.Add(fullName);

                                            // Create the array of flags for each Assembly... this generic example will assume we only
                                            //   want namespaces and types that are public
                                            IntelliPromptNamespaceAndTypeFlags[] flags = new IntelliPromptNamespaceAndTypeFlags[assemblies.Length];
                                            for (int index = 0; index < flags.Length; index++)
                                                flags[index] = IntelliPromptNamespaceAndTypeFlags.NamespacesAndTypes | IntelliPromptNamespaceAndTypeFlags.Public;

                                            // Use the reflection helper method
                                            memberList.AddReflectionForAssemblyNamespacesAndTypes(assemblies, flags, namespaceNames, null, false);

                                            // Loop through the items that were created and add some descriptions
                                            foreach (IntelliPromptMemberListItem item in memberList)
                                            {
                                                if (item.ImageIndex == (int)ActiproSoftware.Products.SyntaxEditor.IconResource.Namespace)
                                                    item.Description = String.Format("namespace <b>{0}</b>", item.Tag.ToString());
                                                else if (item.Tag is Type)
                                                {
                                                    Type type = (Type)item.Tag;
                                                    if (type.IsEnum)
                                                        item.Description = String.Format("enum <b>{0}</b>", type.FullName);
                                                    else if (type.IsInterface)
                                                        item.Description = String.Format("interface <b>{0}</b>", type.FullName);
                                                    else if (type.IsValueType)
                                                        item.Description = String.Format("struct <b>{0}</b>", type.FullName);
                                                    else if (type.IsSubclassOf(typeof(Delegate)))
                                                        item.Description = String.Format("delegate <b>{0}</b>", type.FullName);
                                                    else
                                                        item.Description = String.Format("class <b>{0}</b>", type.FullName);
                                                }
                                            }
                                        }

                                        // Show the list
                                        if (memberList.Count > 0)
                                            memberList.Show();
                                    }
                                    break;
                                }
                        }
                        break;
                    }
            }
        }

        private void editor_ViewMouseDown(object sender, ActiproSoftware.SyntaxEditor.EditorViewMouseEventArgs e)
        {
            switch (e.HitTestResult.Target)
            {
                case SyntaxEditorHitTestTarget.IndicatorMargin:
                    {
                        if (Control.ModifierKeys == Keys.Shift)
                        {
                            // Remove all span indicators from the line
                            editor.SelectedView.CurrentDocumentLine.SpanIndicators.Clear();
                            return;
                        }

                        // Make sure text is selected
                        if (editor.SelectedView.Selection.Length == 0)
                        {
                            MessageBox.Show("Please select some text and re-click within the indicator margin to set a breakpoint over the selected text.");
                            return;
                        }

                        // Add status message
                        this.WriteLine(String.Format("ViewMouseDown: {0} indicator margin clicks on display line {1} at ({2}, {3})", e.Clicks, e.HitTestResult.DisplayLineIndex + 1, e.X, e.Y));

                        if (Control.ModifierKeys == Keys.Control)
                        {
                            // Add a current statement indicator to the line if it doesn't overlap with another indicator (indicators within a layer cannot overlap)
                            SpanIndicatorLayer layer = editor.Document.SpanIndicatorLayers[SpanIndicatorLayer.CurrentStatementKey];
                            if (layer == null)
                            {
                                layer = new SpanIndicatorLayer(SpanIndicatorLayer.CurrentStatementKey, SpanIndicatorLayer.CurrentStatementDisplayPriority);
                                editor.Document.SpanIndicatorLayers.Add(layer);
                            }
                            if (!layer.OverlapsWith(editor.SelectedView.Selection.TextRange))
                                layer.Add(new CurrentStatementSpanIndicator(), editor.SelectedView.Selection.TextRange);
                        }
                        else
                        {
                            // Add a breakpoint to the line if it doesn't overlap with another breakpoint (indicators within a layer cannot overlap)
                            SpanIndicatorLayer layer = editor.Document.SpanIndicatorLayers[SpanIndicatorLayer.BreakpointKey];
                            if (layer == null)
                            {
                                layer = new SpanIndicatorLayer(SpanIndicatorLayer.BreakpointKey, SpanIndicatorLayer.BreakpointDisplayPriority);
                                editor.Document.SpanIndicatorLayers.Add(layer);
                            }
                            if (!layer.OverlapsWith(editor.SelectedView.Selection.TextRange))
                                layer.Add(new BreakpointSpanIndicator(), editor.SelectedView.Selection.TextRange);
                        }
                        break;
                    }
                default:
                    if (e.HitTestResult.Token != null)
                    {
                        // See if the token is a URL token
                        switch (e.HitTestResult.Token.Key)
                        {
                            case "CommentURLToken":
                            case "MultiLineCommentURLToken":
                            case "XMLCommentURLToken":
                                // If the CTRL key is pressed, navigate to the URL
                                if ((e.Button == MouseButtons.Left) && (Control.ModifierKeys == Keys.Control))
                                {
                                    e.Cancel = true;
                                    System.Diagnostics.Process.Start(editor.Document.GetTokenText(e.HitTestResult.Token));
                                }
                                break;
                        }
                    }

                    // Add status message
                    this.WriteLine("ViewMouseDown: " + e.ToString());
                    break;
            }
        }

        private void editor_ViewSplitRemoved(object sender, ActiproSoftware.SyntaxEditor.SyntaxEditorSplitEventArgs e)
        {
            // Add status message
            this.WriteLine("ViewSplitRemoved: " + e.ToString());
        }

        private void editor_TokenMouseEnter(object sender, ActiproSoftware.SyntaxEditor.EditorViewMouseEventArgs e)
        {
            // Add status message
            // this.WriteLine("TokenMouseEnter: " + e.HitTestResult.Token.Key);
        }

        private void editor_ViewSplitMoved(object sender, ActiproSoftware.SyntaxEditor.SyntaxEditorSplitEventArgs e)
        {
            // Add status message
            // this.WriteLine("ViewSplitMoved: " + e.ToString());
        }

        private void editor_DocumentIndicatorResized(object sender, ActiproSoftware.SyntaxEditor.IndicatorEventArgs e)
        {
            // Add status message
            // this.WriteLine("IndicatorResized: " + e.ToString());
        }

        private void editor_CodeSnippetDeactivated(object sender, ActiproSoftware.SyntaxEditor.CodeSnippetEventArgs e)
        {
            this.WriteLine("CodeSnippetDeactivated: " + e.ToString());
        }
        #endregion

        #region status 
        /// <summary>
        /// Sets a status bar message.
        /// </summary>
        /// <param name="text">The text to display.</param>
        public void SetStatusMessage(string text)
        {
            messagePanel.Text = text;
        }
        #endregion
    }
}
